/*
 * led.cpp
 *
 *  Created on: 03.11.2011
 *      Author: g.kruglov
 */
#include "led.h"


// ============================= RGBLed_t ======================================
Led4Ch_t Led;
// ==== LED Thread ====
static WORKING_AREA(waLedThread, 128);
static msg_t LedThread(void *arg) {
    (void)arg;
    chRegSetThreadName("Led");
    while(1) Led.Task();
    return 0;
}

void Led4Ch_t::Init() {
    // ==== Timer ====
	LED_TIM_RCC;
    // ==== Timebase and general ====
	LED_TIM->CR1 = 0x01;       // Enable timer, set clk division to 0, AutoReload not buffered
	LED_TIM->CR2 = 0;          // Output Idle State
	LED_TIM->PSC = 1;          // No clock division
	LED_TIM->ARR = 999;        // Autoreload register: top value of PWM
    // ==== Outputs ====
	LED_TIM->CCMR1 |= 0x6060; // OutPut, PWM 1,2
	LED_TIM->CCMR2 |= 0x6060; // OutPut PWM 3,4
	LED_TIM->CCER = CCER_SETTINGS;
    // Initial values
    SetBright(chOff);
    INeededBright = chOff;
    SleepTime = LED_SETUP_DELAY_LONG_MS;
    // Thread
    PThread = chThdCreateStatic(waLedThread, sizeof(waLedThread), NORMALPRIO, LedThread, NULL);
    // ==== GPIO ====
    IOinit();
}

void Led4Ch_t::SetBrightSmoothly(Channels_t ABright) {
	INeededBright = ABright;
//	Uart.Printf("INeed: %u\r", INeededBright.North);
    if(IsSleeping) {
        chSysLock();
//        Uart.Printf("wup\r");
        chSchWakeupS(PThread, 0);
        IsSleeping = false;
        chSysUnlock();
    }
}

void Led4Ch_t::Task(void) {
    if(ICurrentBright == INeededBright) {
        chSysLock();
        IsSleeping = true;
//        Uart.Printf("susp\r");
        chSchGoSleepS(THD_STATE_SUSPENDED);
        chSysUnlock();
    }
    else {
        // North channel
        if (ICurrentBright.North != INeededBright.North) {
            if(INeededBright.North < ICurrentBright.North) ICurrentBright.North--;
            else ICurrentBright.North++;
        }
        // South channel
        if (ICurrentBright.South != INeededBright.South) {
            if(INeededBright.South < ICurrentBright.South) ICurrentBright.South--;
            else ICurrentBright.South++;
        }
        // West channel
        if (ICurrentBright.West != INeededBright.West) {
            if(INeededBright.West < ICurrentBright.West) ICurrentBright.West--;
            else ICurrentBright.West++;
        }
        // East channel
        if (ICurrentBright.East != INeededBright.East) {
            if(INeededBright.East < ICurrentBright.East) ICurrentBright.East--;
            else ICurrentBright.East++;
        }
//        Uart.Printf("%u : %u : %u : %u\r", ICurrentBright.North, ICurrentBright.South, ICurrentBright.West, ICurrentBright.East);
        SetBright(ICurrentBright);
        SleepTime = (ICurrentBright < clThreshold)? LED_SETUP_DELAY_LONG_MS : LED_SETUP_DELAY_SHORT_MS;
        chThdSleepMilliseconds(SleepTime);
    }
}
